
import os
from pathlib import Path
from urllib.parse import unquote
from io import BytesIO
from PIL import Image
from aiohttp import web


try:
    import aiofiles
    from aiofiles import os as aio_os  # 异步os操作
except ImportError:
    raise ImportError("请安装aiofiles库: pip install aiofiles")

class CacheService:
    @classmethod
    async def cache_image(cls, request: web.Request) -> web.Response:
        temp_path = ""
        try:
            # 接收FormData中的文件和参数
            data = await request.post()

            # 获取图片文件
            file_field = data.get('file')
            if not file_field:
                return web.json_response({
                    "success": False,
                    "message": "未提供图片文件"
                })

            # 获取缓存路径参数
            cache_path_str = data.get('cachePath')
            if not cache_path_str or not isinstance(cache_path_str, str):
                return web.json_response({
                    "success": False,
                    "message": "无效的缓存路径"
                })

            # 解码URL编码的缓存路径
            decoded_cache_path = unquote(cache_path_str)
            cache_path = Path(decoded_cache_path)

            # 构建WebP缓存路径
            webp_cache_path = cache_path.with_suffix('.webp')
            cache_dir = webp_cache_path.parent

            # 生成临时文件路径
            temp_path = f"{str(webp_cache_path)}.tmp-{os.urandom(8).hex()}"

            # 确保目录存在
            loop = request.app.loop
            await loop.run_in_executor(
                None,
                lambda: os.makedirs(cache_dir, exist_ok=True, mode=0o755)
            )

            try:
                # 读取上传的图片数据
                image_data = file_field.file.read()

                # 验证图片数据
                if not image_data:
                    return web.json_response({
                        "success": False,
                        "message": "无效的图片数据"
                    })

                # 使用PIL处理图片并转换为WebP（在executor中运行同步操作）
                await loop.run_in_executor(
                    None,
                    cls._convert_to_webp,
                    image_data,
                    temp_path
                )

                # 原子性重命名临时文件到目标路径
                await loop.run_in_executor(
                    None,
                    lambda: os.replace(temp_path, str(webp_cache_path))
                )

                # 获取文件信息
                file_stats = await loop.run_in_executor(
                    None,
                    lambda: os.stat(str(webp_cache_path))
                )

                return web.json_response({
                    "success": True,
                    "message": "图片以WebP格式缓存完成",
                    "data": {
                        "cachePath": str(webp_cache_path),
                        "fileSize": file_stats.st_size
                    }
                })

            except Exception as conversion_error:
                return web.json_response({
                    "success": False,
                    "message": f"缓存失败: {str(conversion_error)}"
                })

        except Exception as main_error:
            return web.json_response({
                "success": False,
                "message": f"缓存图片时出错: {str(main_error)}"
            })
        finally:
            # 清理临时文件
            if temp_path and os.path.exists(temp_path):
                try:
                    await request.app.loop.run_in_executor(
                        None,
                        lambda: os.unlink(temp_path)
                    )
                except Exception as cleanup_error:
                    # 只处理非文件不存在的错误
                    if isinstance(cleanup_error, OSError) and cleanup_error.errno != 2:
                        print(f"临时文件清理错误: {str(cleanup_error)}")

    @staticmethod
    def _convert_to_webp(image_data: bytes, output_path: str) -> None:
        """同步图片转换为WebP格式"""
        with Image.open(BytesIO(image_data)) as img:
            # 处理不同图片模式
            if img.mode in ('RGBA', 'LA'):
                # 处理透明背景，替换为白色
                background = Image.new(img.mode[:-1], img.size, (255, 255, 255))
                background.paste(img, img.split()[-1])
                img = background
            elif img.mode == 'P':
                # 处理调色板模式
                img = img.convert('RGB')

            # 保存为WebP格式，质量90
            img.save(output_path, 'WebP', quality=90, lossless=False)
